package org.etlt.job.config.xml;

import org.etlt.job.DatasourceResourceSetting;
import org.etlt.job.JobContext;
import org.etlt.job.JobSetting;
import org.etlt.job.ResourceSetting;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @Deprecated
 * @see JobSettingXmlSimplerResolver
 */
@Deprecated
public class JobSettingXmlResolver extends AbstractSettingXmlResolver<JobSetting> {

    public JobSettingXmlResolver() {

    }

    @Override
    public JobSetting resolve(InputStream stream, JobContext context) {
        try {
            JobSetting jobSetting = new JobSetting();
            parse(jobSetting, stream, context);
            return jobSetting;
        } catch (Exception e) {
            throw new IllegalStateException("job.xml parse error.", e);
        }
    }

    protected void parse(JobSetting jobSetting, InputStream input, JobContext context) throws Exception {
        Document document = getDocumentBuilder().parse(input);
        Element root = document.getDocumentElement();
        SegmentParser sp = getParserFactory().get(root.getNodeName());
        sp.parse(jobSetting, root, context);
    }


    protected void registerParser() {
        getParserFactory().put("job", (jobSetting, node, context) -> {
            Element element = (Element) node;
            jobSetting.setName(element.getAttribute("name"));
            NodeList children = element.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                Node child = children.item(i);
                if (child.getNodeType() == Node.ELEMENT_NODE) {
                    SegmentParser sp = getParserFactory().get(child.getNodeName());
                    if (sp != null)
                        sp.parse(jobSetting, child, null);
                }
            }
            return jobSetting;
        });

        getParserFactory().put("properties", (jobSetting, node, context) -> {
            String propertyTag = "property";
            NodeList extractors = ((Element) node).getElementsByTagName(propertyTag);
            for (int i = 0; i < extractors.getLength(); i++) {
                Element property = (Element) extractors.item(i);
                getParserFactory().get(propertyTag).parse(jobSetting, property, context);
            }
            return jobSetting;
        });

        getParserFactory().put("property", (jobSetting, node, context) -> {
            Element element = (Element) node;
            String name = ((Element) node).getAttribute("name");
            String value = element.getTextContent();
            jobSetting.getProperties().put(name, value);
            return jobSetting;
        });

        getParserFactory().put("parallel", (jobSetting, node, context) -> {
            String par = node.getTextContent();
            if (par != null)
                jobSetting.setParallel(Integer.parseInt(par));
            return jobSetting;
        });

        getParserFactory().put("extractors", (jobSetting, node, context) -> {
            String extractorTag = "extractor";
            NodeList extractors = ((Element) node).getElementsByTagName(extractorTag);
            for (int i = 0; i < extractors.getLength(); i++) {
                Element extractor = (Element) extractors.item(i);
                getParserFactory().get(extractorTag).parse(jobSetting, extractor, context);
            }
            return jobSetting;
        });

        getParserFactory().put("extractor", ((jobSetting, node, context) -> {
            Element extractorE = (Element) node;
            String name = extractorE.getAttribute("location");
            List<String> extractors = jobSetting.getExtractors();
            if (extractors == null) {
                extractors = new ArrayList<>();
            }
            extractors.add(name);
            jobSetting.setExtractors(extractors);
            return jobSetting;
        }));

        getParserFactory().put("loaders", ((jobSetting, node, context) -> {
            String loaderTag = "loader";
            NodeList loaders = ((Element) node).getElementsByTagName(loaderTag);
            for (int i = 0; i < loaders.getLength(); i++) {
                Element loader = (Element) loaders.item(i);
                getParserFactory().get(loaderTag).parse(jobSetting, loader, context);
            }
            return jobSetting;
        }));

        getParserFactory().put("loader", ((jobSetting, node, context) -> {
            Element loaderE = (Element) node;
            String location = loaderE.getAttribute("location");
            List<String> loaders = jobSetting.getLoaders();
            if (loaders == null) {
                loaders = new ArrayList<>();
            }
            loaders.add(location);
            jobSetting.setLoaders(loaders);
            return jobSetting;
        }));

        getParserFactory().put("mappings", ((jobSetting, node, context) -> {
            String mappingTag = "mapping";
            NodeList mappings = ((Element) node).getElementsByTagName(mappingTag);
            for (int i = 0; i < mappings.getLength(); i++) {
                Element mapping = (Element) mappings.item(i);
                getParserFactory().get(mappingTag).parse(jobSetting, mapping, context);
            }
            return jobSetting;
        }));

        getParserFactory().put("mapping", ((jobSetting, node, context) -> {
            Element mappingE = (Element) node;
            String location = mappingE.getAttribute("location");
            List<String> mappings = jobSetting.getMappings();
            if (mappings == null) {
                mappings = new ArrayList<>();
            }
            mappings.add(location);
            jobSetting.setMappings(mappings);
            return jobSetting;
        }));

        getParserFactory().put("resources", ((jobSetting, node, context) -> {
            String resourceTag = "resource";
            NodeList resources = ((Element) node).getElementsByTagName(resourceTag);
            for (int i = 0; i < resources.getLength(); i++) {
                Element mapping = (Element) resources.item(i);
                getParserFactory().get(resourceTag).parse(jobSetting, mapping, context);
            }
            return jobSetting;
        }));

        getParserFactory().put("resource", ((jobSetting, node, context) -> {
            Element resourceE = (Element) node;
            String name = resourceE.getAttribute("name");
            String type = resourceE.getAttribute("type");
            switch (type) {
                case ResourceSetting.DATA_BASE_RESOURCE:
                    DatasourceResourceSetting resourceSetting = new DatasourceResourceSetting();
                    resourceSetting.setName(name);
                    resourceSetting.setType(type);
                    resourceSetting.setClassName(
                            jobSetting.getPropertyValue(
                                    getFirstChildValueByName(resourceE, "className")));
                    resourceSetting.setUrl(
                            jobSetting.getPropertyValue(
                                    getFirstChildValueByName(resourceE, "url")));
                    resourceSetting.setUser(
                            jobSetting.getPropertyValue(
                                    getFirstChildValueByName(resourceE, "user")));
                    resourceSetting.setPassword(
                            jobSetting.getPropertyValue(
                                    getFirstChildValueByName(resourceE, "password")));
                    resourceSetting.setValidationQuery(
                            jobSetting.getPropertyValue(
                                    getFirstChildValueByName(resourceE, "validationQuery")));
                    resourceSetting.setInitialSize(
                            Integer.parseInt(
                                    jobSetting.getPropertyValue(
                                            getFirstChildValueByName(resourceE, "initialSize"))));
                    resourceSetting.setMaxIdle(
                            Integer.parseInt(jobSetting.getPropertyValue(getFirstChildValueByName(resourceE, "maxIdle"))));
                    resourceSetting.setMaxActive(
                            Integer.parseInt(jobSetting.getPropertyValue(getFirstChildValueByName(resourceE, "maxActive"))));
                    jobSetting.getResources().add(resourceSetting);
                    break;
                default:
                    break;
            }
            return jobSetting;
        }));
    }


}
